/*
 * LvObj.h
 *
 *  Created on:
 *      Author: fstuffdev
 */

#ifndef LVOBJ_H_
#define LVOBJ_H_

#include <list>
#include "LvEvent.h"
#include "lvglpp.h"
#include "../misc/LvStyle.h"
#include <concepts>

namespace lvglpp
{
	template <typename T>
	struct LvProtypeTraits;

	template <>
	struct LvProtypeTraits<lv_obj_t>
	{
		using TWrapped = LvTObj<lv_obj_t>;
		static constexpr auto &obj_class = lv_obj_class;
		static constexpr auto create = lv_obj_create;
	};

	namespace _lv
	{
		template <typename WRAPPED>
		struct WrappedTraits;

		template <template <typename> class SUBTMP, typename T>
		struct WrappedTraits<SUBTMP<T>>
		{
			template <typename PROTYPE>
			using apply = SUBTMP<PROTYPE>;
		};

		template <typename T>
		struct ProtypeTraits;

		template <typename T>
		struct ProtypeTraits<T *>;

		template <typename T>
		struct ProtypeTraits<T &>;

		template <typename T>
		requires requires { LvProtypeTraits<T>{}; }
		struct ProtypeTraits<T>
		{
			using TObject = T;
			using TProtype = T;
			using TWrapped = typename LvProtypeTraits<T>::TWrapped;
			static inline lv_obj_t *get(TObject &obj) noexcept
			{
				if constexpr (std::same_as<T, lv_obj_t>)
					return &obj;
				else if constexpr (requires { {LvProtypeTraits<T>::get(obj)}->std::convertible_to<lv_obj_t&>; })
					return &static_cast<lv_obj_t &>(LvProtypeTraits<T>::get(obj));
				else
					return &obj.obj;
			}
			static inline const lv_obj_t *get(const TObject &obj) noexcept { return get(const_cast<TObject &>(obj)); }
			static constexpr auto &obj_class = LvProtypeTraits<T>::obj_class;
			static constexpr auto create = LvProtypeTraits<T>::create;
			template <typename PROTYPE>
			static constexpr bool HasParent = std::derived_from<TWrapped, typename WrappedTraits<typename ProtypeTraits<PROTYPE>::TWrapped>::template apply<TProtype>>;
		};

		template <typename T>
		requires requires { LvProtypeTraits<T>{}; }
		struct ProtypeTraits<T &&>
		{
			struct TObject
			{
				LvPointer<lv_obj_t, lv_obj_del> handle;
				inline TObject(lv_obj_t *ptr) noexcept : handle(ptr) {}
			};
			using TProtype = T &&;
			using TWrapped = typename WrappedTraits<typename LvProtypeTraits<T>::TWrapped>::template apply<TProtype>;
			static inline lv_obj_t *get(const TObject &obj) noexcept { return ProtypeTraits<T>::get((T &)*obj.handle); }
			static constexpr auto &obj_class = LvProtypeTraits<T>::obj_class;
			static constexpr auto create = LvProtypeTraits<T>::create;
			template <typename PROTYPE>
			static constexpr bool HasParent = std::derived_from<TWrapped, typename WrappedTraits<typename ProtypeTraits<PROTYPE>::TWrapped>::template apply<TProtype>>;
		};

		struct as_handle_tag
		{
		};
	} // namespace _lv

	template <typename PROTYPE>
	requires requires { LvProtypeTraits<std::remove_const_t<PROTYPE>>{}; }
	class LvRawPtr
	{
		using TRaw = PROTYPE;
		template <typename T>
		using TCLike = std::conditional_t<std::is_const_v<TRaw>, const T, T>;
		using TWrapped = TCLike<typename LvProtypeTraits<std::remove_const_t<TRaw>>::TWrapped>;
		TWrapped *ptr;

	public:
		LvRawPtr() = default;
		inline explicit constexpr LvRawPtr(TCLike<lv_obj_t> *p) noexcept : ptr((TWrapped *)p) {}
		inline constexpr LvRawPtr(TRaw *p) noexcept requires(!std::same_as<TRaw, lv_obj_t>) : ptr((TWrapped *)p) {}
		inline constexpr LvRawPtr(TWrapped *oth) noexcept : ptr(oth) {}
		inline constexpr LvRawPtr(std::nullptr_t) noexcept : ptr(nullptr) {}
		template <typename SPROTYPE> requires(_lv::ProtypeTraits<std::remove_const_t<SPROTYPE>>::template HasParent<std::remove_const_t<TRaw>> && (std::is_const_v<TRaw> || !std::is_const_v<SPROTYPE>))
		inline LvRawPtr(LvRawPtr<SPROTYPE> oth) noexcept : ptr((TWrapped *&)oth) {}

		template <typename OTH>
		inline constexpr LvRawPtr(LvTObj<OTH> *oth) noexcept requires(requires { LvRawPtr(oth->raw()); }) : LvRawPtr(oth->raw()) {}

		template <typename OTH>
		inline constexpr LvRawPtr(LvTObj<OTH &&> *oth) noexcept requires(requires { LvRawPtr(oth->raw()); }) : LvRawPtr(oth ? oth->raw() : nullptr) {}

		template <typename OTH>
		inline constexpr LvRawPtr(LvTObj<OTH> &oth) noexcept requires(requires { LvRawPtr(oth.raw()); }) : LvRawPtr(oth.raw()) {}

	public:
		explicit inline operator bool() const noexcept { return ptr != nullptr; }
		inline operator TRaw *() const noexcept { return (TRaw *)ptr; }
		inline operator TCLike<lv_obj_t> *() const noexcept requires(!std::same_as<TRaw, TCLike<lv_obj_t>>) { return (TCLike<lv_obj_t> *)ptr; }
		inline TWrapped &operator*() const noexcept { return *(TWrapped *)ptr; }
		inline TWrapped *operator->() const noexcept { return (TWrapped *)ptr; }
	};
	template <typename PROTYPE>
	requires requires { LvProtypeTraits<std::remove_const_t<PROTYPE>>{}; }
	LvRawPtr(PROTYPE *) -> LvRawPtr<PROTYPE>;

	using LvObjPtr = LvRawPtr<lv_obj_t>;
	class LvGroup;

	template <typename PROTYPE>
	class LvTObj
	{
		using TTraits = _lv::ProtypeTraits<PROTYPE>;
		using TObject = typename TTraits::TObject;
		using TProtype = typename TTraits::TProtype;
		using THandle = std::add_pointer_t<TProtype>;

		template <typename OPROTYPE>
		friend class LvTObj;

	protected:
		static constexpr bool IsHandle = std::is_reference_v<TProtype>;

		template <template <typename> class IMP, typename T>
		static constexpr bool _canReferencedBy = std::derived_from<IMP<T>, LvTObj<T>> && TTraits::template HasParent<T> && (!std::is_reference_v<T> || std::is_reference_v<TProtype>);

	private:
		TObject _obj;

	public:
		using RawPtr = LvRawPtr<std::remove_reference_t<TProtype>>;
		using ConstRawPtr = LvRawPtr<const std::remove_reference_t<TProtype>>;

	protected:
		using TSelf = typename TTraits::TWrapped;
		inline TSelf &_self() noexcept { return static_cast<TSelf &>(*this); }
		inline const TSelf &_self() const noexcept { return static_cast<const TSelf &>(*this); }
		inline TSelf &setCObj(THandle ptr) noexcept requires(IsHandle) { return _obj.handle.reset(ptr), _self(); }
		LvTObj() requires(!IsHandle) = default;
		LvTObj(const LvTObj &) = delete;

		static inline lv_obj_t *_create(lv_obj_t *parent) noexcept
		{
			static_assert(sizeof(TSelf) == sizeof(TObject) && std::derived_from<TSelf, LvTObj>);
			return TTraits::create(parent);
		}

	public:
		static inline RawPtr create(lv_obj_t *Parent) noexcept { return RawPtr(_create(Parent ? Parent : lv_scr_act())); }
		static inline RawPtr create(std::nullptr_t) = delete;
		static inline RawPtr create() noexcept { return RawPtr(_create(lv_scr_act())); }

		template <typename OPROTYPE>
		static inline RawPtr create(LvTObj<OPROTYPE> *Parent) noexcept { return RawPtr(_create(Parent ? Parent->raw() : lv_scr_act())); }

		template <typename OPROTYPE>
		static inline RawPtr create(LvTObj<OPROTYPE> &Parent) noexcept { return RawPtr(_create(Parent.raw())); }

		LvTObj(LvTObj &&) requires IsHandle = default;

		template <typename... P> requires IsHandle && requires(P &&...Parent) { create(std::forward<P>(Parent)...); }
		inline explicit LvTObj(P &&...Parent) noexcept : _obj(create(std::forward<P>(Parent)...)) {}

		static constexpr auto AsHandle = _lv::as_handle_tag{};

		inline explicit LvTObj(TProtype &handle, decltype(AsHandle)) noexcept requires IsHandle : _obj((lv_obj_t *)&handle) {}

		inline RawPtr raw() noexcept { return RawPtr{TTraits::get(_obj)}; }
		inline ConstRawPtr raw() const noexcept { return ConstRawPtr{TTraits::get(_obj)}; }
		inline RawPtr Detach() noexcept requires IsHandle { return RawPtr{_obj.handle.release()}; }

		template <template <typename> class IMP, typename T>
		requires _canReferencedBy<IMP, T>
		inline operator IMP<T> &() noexcept
		{
			if constexpr (std::is_rvalue_reference_v<T> && std::is_rvalue_reference_v<TProtype>)
				return *(IMP<T> *)this;
			else if constexpr (!std::is_reference_v<T>)
				return *(IMP<T> *)&*raw();
		}

		template <template <typename> class IMP, typename T>
		requires _canReferencedBy<IMP, T>
		inline operator const IMP<T> &() const noexcept
		{
			if constexpr (std::is_rvalue_reference_v<T> && std::is_rvalue_reference_v<TProtype>)
				return *(const IMP<T> *)this;
			else if constexpr (!std::is_reference_v<T>)
				return *(const IMP<T> *)&*raw();
		}

		template <typename T>
		bool checkType() const noexcept { return checkType(&T::TTraits::obj_class); }

		template <typename T>
		bool hasClass() const noexcept { return hasClass(&T::TTraits::obj_class); }

	public:
		//+gen
		inline TSelf &setPos(lv_coord_t x, lv_coord_t y) { return lv_obj_set_pos(raw(), x, y), _self(); }
		inline TSelf &setX(lv_coord_t x) { return lv_obj_set_x(raw(), x), _self(); }
		inline TSelf &setY(lv_coord_t y) { return lv_obj_set_y(raw(), y), _self(); }
		inline TSelf &setSize(lv_coord_t w, lv_coord_t h) { return lv_obj_set_size(raw(), w, h), _self(); }
		inline bool refrSize() { return lv_obj_refr_size(raw()); }
		inline TSelf &setWidth(lv_coord_t w) { return lv_obj_set_width(raw(), w), _self(); }
		inline TSelf &setHeight(lv_coord_t h) { return lv_obj_set_height(raw(), h), _self(); }
		inline TSelf &setContentWidth(lv_coord_t w) { return lv_obj_set_content_width(raw(), w), _self(); }
		inline TSelf &setContentHeight(lv_coord_t h) { return lv_obj_set_content_height(raw(), h), _self(); }
		inline TSelf &setLayout(uint32_t layout) { return lv_obj_set_layout(raw(), layout), _self(); }
		inline bool isLayoutPositioned() const { return lv_obj_is_layout_positioned(raw()); }
		inline TSelf &markLayoutAsDirty() { return lv_obj_mark_layout_as_dirty(raw()), _self(); }
		inline const TSelf &updateLayout() const { return lv_obj_update_layout(raw()), _self(); }
		inline TSelf &setAlign(lv_align_t align) { return lv_obj_set_align(raw(), align), _self(); }
		inline TSelf &align(lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) { return lv_obj_align(raw(), align, x_ofs, y_ofs), _self(); }
		inline TSelf &alignTo(const struct _lv_obj_t *base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) { return lv_obj_align_to(raw(), base, align, x_ofs, y_ofs), _self(); }
		inline TSelf &center() { return lv_obj_center(raw()), _self(); }
		inline const TSelf &getCoords(lv_area_t *coords) const { return lv_obj_get_coords(raw(), coords), _self(); }
		inline lv_coord_t getX() const { return lv_obj_get_x(raw()); }
		inline lv_coord_t getX2() const { return lv_obj_get_x2(raw()); }
		inline lv_coord_t getY() const { return lv_obj_get_y(raw()); }
		inline lv_coord_t getY2() const { return lv_obj_get_y2(raw()); }
		inline lv_coord_t getXAligned() const { return lv_obj_get_x_aligned(raw()); }
		inline lv_coord_t getYAligned() const { return lv_obj_get_y_aligned(raw()); }
		inline lv_coord_t getWidth() const { return lv_obj_get_width(raw()); }
		inline lv_coord_t getHeight() const { return lv_obj_get_height(raw()); }
		inline lv_coord_t getContentWidth() const { return lv_obj_get_content_width(raw()); }
		inline lv_coord_t getContentHeight() const { return lv_obj_get_content_height(raw()); }
		inline const TSelf &getContentCoords(lv_area_t *area) const { return lv_obj_get_content_coords(raw(), area), _self(); }
		inline lv_coord_t getSelfWidth() const { return lv_obj_get_self_width(raw()); }
		inline lv_coord_t getSelfHeight() const { return lv_obj_get_self_height(raw()); }
		inline bool refreshSelfSize() { return lv_obj_refresh_self_size(raw()); }
		inline TSelf &refrPos() { return lv_obj_refr_pos(raw()), _self(); }
		inline TSelf &moveTo(lv_coord_t x, lv_coord_t y) { return lv_obj_move_to(raw(), x, y), _self(); }
		inline TSelf &moveChildrenBy(lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating) { return lv_obj_move_children_by(raw(), x_diff, y_diff, ignore_floating), _self(); }
		inline const TSelf &invalidateArea(const lv_area_t *area) const { return lv_obj_invalidate_area(raw(), area), _self(); }
		inline const TSelf &invalidate() const { return lv_obj_invalidate(raw()), _self(); }
		inline bool areaIsVisible(lv_area_t *area) const { return lv_obj_area_is_visible(raw(), area); }
		inline bool isVisible() const { return lv_obj_is_visible(raw()); }
		inline TSelf &setExtClickArea(lv_coord_t size) { return lv_obj_set_ext_click_area(raw(), size), _self(); }
		inline const TSelf &getClickArea(lv_area_t *area) const { return lv_obj_get_click_area(raw(), area), _self(); }
		inline bool hitTest(const lv_point_t *point) { return lv_obj_hit_test(raw(), point); }
		inline TSelf &del() { return lv_obj_del(raw()), _self(); }
		inline TSelf &clean() { return lv_obj_clean(raw()), _self(); }
		inline TSelf &delDelayed(uint32_t delay_ms) { return lv_obj_del_delayed(raw(), delay_ms), _self(); }
		inline TSelf &delAnimReadyCb() { return lv_obj_del_anim_ready_cb(raw()), _self(); }
		inline TSelf &delAsync() { return lv_obj_del_async(raw()), _self(); }
		inline TSelf &setParent(struct _lv_obj_t *parent) { return lv_obj_set_parent(raw(), parent), _self(); }
		inline TSelf &swap(struct _lv_obj_t *obj2) { return lv_obj_swap(raw(), obj2), _self(); }
		inline TSelf &moveToIndex(int32_t index) { return lv_obj_move_to_index(raw(), index), _self(); }
		inline LvObjPtr getScreen() const { return (LvObjPtr)lv_obj_get_screen(raw()); }
		inline lv_disp_t *getDisp() const { return lv_obj_get_disp(raw()); }
		inline LvObjPtr getParent() const { return (LvObjPtr)lv_obj_get_parent(raw()); }
		inline LvObjPtr getChild(int32_t id) const { return (LvObjPtr)lv_obj_get_child(raw(), id); }
		inline uint32_t getChildCnt() const { return lv_obj_get_child_cnt(raw()); }
		inline uint32_t getIndex() const { return lv_obj_get_index(raw()); }
		inline TSelf &treeWalk(lv_obj_tree_walk_cb_t cb, void *user_data) { return lv_obj_tree_walk(raw(), cb, user_data), _self(); }
		inline TSelf &setScrollbarMode(lv_scrollbar_mode_t mode) { return lv_obj_set_scrollbar_mode(raw(), mode), _self(); }
		inline TSelf &setScrollDir(lv_dir_t dir) { return lv_obj_set_scroll_dir(raw(), dir), _self(); }
		inline TSelf &setScrollSnapX(lv_scroll_snap_t align) { return lv_obj_set_scroll_snap_x(raw(), align), _self(); }
		inline TSelf &setScrollSnapY(lv_scroll_snap_t align) { return lv_obj_set_scroll_snap_y(raw(), align), _self(); }
		inline lv_scrollbar_mode_t getScrollbarMode() const { return lv_obj_get_scrollbar_mode(raw()); }
		inline lv_dir_t getScrollDir() const { return lv_obj_get_scroll_dir(raw()); }
		inline lv_scroll_snap_t getScrollSnapX() const { return lv_obj_get_scroll_snap_x(raw()); }
		inline lv_scroll_snap_t getScrollSnapY() const { return lv_obj_get_scroll_snap_y(raw()); }
		inline lv_coord_t getScrollX() const { return lv_obj_get_scroll_x(raw()); }
		inline lv_coord_t getScrollY() const { return lv_obj_get_scroll_y(raw()); }
		inline lv_coord_t getScrollTop() { return lv_obj_get_scroll_top(raw()); }
		inline lv_coord_t getScrollBottom() { return lv_obj_get_scroll_bottom(raw()); }
		inline lv_coord_t getScrollLeft() { return lv_obj_get_scroll_left(raw()); }
		inline lv_coord_t getScrollRight() { return lv_obj_get_scroll_right(raw()); }
		inline TSelf &getScrollEnd(lv_point_t *end) { return lv_obj_get_scroll_end(raw(), end), _self(); }
		inline TSelf &scrollBy(lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) { return lv_obj_scroll_by(raw(), x, y, anim_en), _self(); }
		inline TSelf &scrollByBounded(lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en) { return lv_obj_scroll_by_bounded(raw(), dx, dy, anim_en), _self(); }
		inline TSelf &scrollTo(lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) { return lv_obj_scroll_to(raw(), x, y, anim_en), _self(); }
		inline TSelf &scrollToX(lv_coord_t x, lv_anim_enable_t anim_en) { return lv_obj_scroll_to_x(raw(), x, anim_en), _self(); }
		inline TSelf &scrollToY(lv_coord_t y, lv_anim_enable_t anim_en) { return lv_obj_scroll_to_y(raw(), y, anim_en), _self(); }
		inline TSelf &scrollToView(lv_anim_enable_t anim_en) { return lv_obj_scroll_to_view(raw(), anim_en), _self(); }
		inline TSelf &scrollToViewRecursive(lv_anim_enable_t anim_en) { return lv_obj_scroll_to_view_recursive(raw(), anim_en), _self(); }
		inline bool isScrolling() const { return lv_obj_is_scrolling(raw()); }
		inline TSelf &updateSnap(lv_anim_enable_t anim_en) { return lv_obj_update_snap(raw(), anim_en), _self(); }
		inline TSelf &getScrollbarArea(lv_area_t *hor, lv_area_t *ver) { return lv_obj_get_scrollbar_area(raw(), hor, ver), _self(); }
		inline TSelf &scrollbarInvalidate() { return lv_obj_scrollbar_invalidate(raw()), _self(); }
		inline TSelf &readjustScroll(lv_anim_enable_t anim_en) { return lv_obj_readjust_scroll(raw(), anim_en), _self(); }
		inline TSelf &addStyle(lv_style_t *style, lv_style_selector_t selector) { return lv_obj_add_style(raw(), style, selector), _self(); }
		inline TSelf &removeStyle(lv_style_t *style, lv_style_selector_t selector) { return lv_obj_remove_style(raw(), style, selector), _self(); }
		inline TSelf &removeStyleAll() { return lv_obj_remove_style_all(raw()), _self(); }
		inline TSelf &reportStyleChange() { return lv_obj_report_style_change(raw()), _self(); }
		inline TSelf &refreshStyle(lv_part_t part, lv_style_prop_t prop) { return lv_obj_refresh_style(raw(), part, prop), _self(); }
		static inline void enableStyleRefresh(bool en) { return lv_obj_enable_style_refresh(en); }
		inline lv_style_value_t getStyleProp(lv_part_t part, lv_style_prop_t prop) const { return lv_obj_get_style_prop(raw(), part, prop); }
		inline TSelf &setLocalStyleProp(lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) { return lv_obj_set_local_style_prop(raw(), prop, value, selector), _self(); }
		inline lv_res_t getLocalStyleProp(lv_style_prop_t prop, lv_style_value_t *value, lv_style_selector_t selector) { return lv_obj_get_local_style_prop(raw(), prop, value, selector); }
		inline bool removeLocalStyleProp(lv_style_prop_t prop, lv_style_selector_t selector) { return lv_obj_remove_local_style_prop(raw(), prop, selector); }
		inline TSelf &fadeIn(uint32_t time, uint32_t delay) { return lv_obj_fade_in(raw(), time, delay), _self(); }
		inline TSelf &fadeOut(uint32_t time, uint32_t delay) { return lv_obj_fade_out(raw(), time, delay), _self(); }
		static inline lv_state_t styleGetSelectorState(lv_style_selector_t selector) { return lv_obj_style_get_selector_state(selector); }
		static inline lv_part_t styleGetSelectorPart(lv_style_selector_t selector) { return lv_obj_style_get_selector_part(selector); }
		inline lv_coord_t getStyleWidth(uint32_t part) const { return lv_obj_get_style_width(raw(), part); }
		inline lv_coord_t getStyleMinWidth(uint32_t part) const { return lv_obj_get_style_min_width(raw(), part); }
		inline lv_coord_t getStyleMaxWidth(uint32_t part) const { return lv_obj_get_style_max_width(raw(), part); }
		inline lv_coord_t getStyleHeight(uint32_t part) const { return lv_obj_get_style_height(raw(), part); }
		inline lv_coord_t getStyleMinHeight(uint32_t part) const { return lv_obj_get_style_min_height(raw(), part); }
		inline lv_coord_t getStyleMaxHeight(uint32_t part) const { return lv_obj_get_style_max_height(raw(), part); }
		inline lv_coord_t getStyleX(uint32_t part) const { return lv_obj_get_style_x(raw(), part); }
		inline lv_coord_t getStyleY(uint32_t part) const { return lv_obj_get_style_y(raw(), part); }
		inline lv_align_t getStyleAlign(uint32_t part) const { return lv_obj_get_style_align(raw(), part); }
		inline lv_coord_t getStyleTransformWidth(uint32_t part) const { return lv_obj_get_style_transform_width(raw(), part); }
		inline lv_coord_t getStyleTransformHeight(uint32_t part) const { return lv_obj_get_style_transform_height(raw(), part); }
		inline lv_coord_t getStyleTranslateX(uint32_t part) const { return lv_obj_get_style_translate_x(raw(), part); }
		inline lv_coord_t getStyleTranslateY(uint32_t part) const { return lv_obj_get_style_translate_y(raw(), part); }
		inline lv_coord_t getStyleTransformZoom(uint32_t part) const { return lv_obj_get_style_transform_zoom(raw(), part); }
		inline lv_coord_t getStyleTransformAngle(uint32_t part) const { return lv_obj_get_style_transform_angle(raw(), part); }
		inline lv_coord_t getStylePadTop(uint32_t part) const { return lv_obj_get_style_pad_top(raw(), part); }
		inline lv_coord_t getStylePadBottom(uint32_t part) const { return lv_obj_get_style_pad_bottom(raw(), part); }
		inline lv_coord_t getStylePadLeft(uint32_t part) const { return lv_obj_get_style_pad_left(raw(), part); }
		inline lv_coord_t getStylePadRight(uint32_t part) const { return lv_obj_get_style_pad_right(raw(), part); }
		inline lv_coord_t getStylePadRow(uint32_t part) const { return lv_obj_get_style_pad_row(raw(), part); }
		inline lv_coord_t getStylePadColumn(uint32_t part) const { return lv_obj_get_style_pad_column(raw(), part); }
		inline lv_color_t getStyleBgColor(uint32_t part) const { return lv_obj_get_style_bg_color(raw(), part); }
		inline lv_color_t getStyleBgColorFiltered(uint32_t part) const { return lv_obj_get_style_bg_color_filtered(raw(), part); }
		inline lv_opa_t getStyleBgOpa(uint32_t part) const { return lv_obj_get_style_bg_opa(raw(), part); }
		inline lv_color_t getStyleBgGradColor(uint32_t part) const { return lv_obj_get_style_bg_grad_color(raw(), part); }
		inline lv_color_t getStyleBgGradColorFiltered(uint32_t part) const { return lv_obj_get_style_bg_grad_color_filtered(raw(), part); }
		inline lv_grad_dir_t getStyleBgGradDir(uint32_t part) const { return lv_obj_get_style_bg_grad_dir(raw(), part); }
		inline lv_coord_t getStyleBgMainStop(uint32_t part) const { return lv_obj_get_style_bg_main_stop(raw(), part); }
		inline lv_coord_t getStyleBgGradStop(uint32_t part) const { return lv_obj_get_style_bg_grad_stop(raw(), part); }
		inline const lv_grad_dsc_t *getStyleBgGrad(uint32_t part) const { return lv_obj_get_style_bg_grad(raw(), part); }
		inline lv_dither_mode_t getStyleBgDitherMode(uint32_t part) const { return lv_obj_get_style_bg_dither_mode(raw(), part); }
		inline const void *getStyleBgImgSrc(uint32_t part) const { return lv_obj_get_style_bg_img_src(raw(), part); }
		inline lv_opa_t getStyleBgImgOpa(uint32_t part) const { return lv_obj_get_style_bg_img_opa(raw(), part); }
		inline lv_color_t getStyleBgImgRecolor(uint32_t part) const { return lv_obj_get_style_bg_img_recolor(raw(), part); }
		inline lv_color_t getStyleBgImgRecolorFiltered(uint32_t part) const { return lv_obj_get_style_bg_img_recolor_filtered(raw(), part); }
		inline lv_opa_t getStyleBgImgRecolorOpa(uint32_t part) const { return lv_obj_get_style_bg_img_recolor_opa(raw(), part); }
		inline bool getStyleBgImgTiled(uint32_t part) const { return lv_obj_get_style_bg_img_tiled(raw(), part); }
		inline lv_color_t getStyleBorderColor(uint32_t part) const { return lv_obj_get_style_border_color(raw(), part); }
		inline lv_color_t getStyleBorderColorFiltered(uint32_t part) const { return lv_obj_get_style_border_color_filtered(raw(), part); }
		inline lv_opa_t getStyleBorderOpa(uint32_t part) const { return lv_obj_get_style_border_opa(raw(), part); }
		inline lv_coord_t getStyleBorderWidth(uint32_t part) const { return lv_obj_get_style_border_width(raw(), part); }
		inline lv_border_side_t getStyleBorderSide(uint32_t part) const { return lv_obj_get_style_border_side(raw(), part); }
		inline bool getStyleBorderPost(uint32_t part) const { return lv_obj_get_style_border_post(raw(), part); }
		inline lv_coord_t getStyleOutlineWidth(uint32_t part) const { return lv_obj_get_style_outline_width(raw(), part); }
		inline lv_color_t getStyleOutlineColor(uint32_t part) const { return lv_obj_get_style_outline_color(raw(), part); }
		inline lv_color_t getStyleOutlineColorFiltered(uint32_t part) const { return lv_obj_get_style_outline_color_filtered(raw(), part); }
		inline lv_opa_t getStyleOutlineOpa(uint32_t part) const { return lv_obj_get_style_outline_opa(raw(), part); }
		inline lv_coord_t getStyleOutlinePad(uint32_t part) const { return lv_obj_get_style_outline_pad(raw(), part); }
		inline lv_coord_t getStyleShadowWidth(uint32_t part) const { return lv_obj_get_style_shadow_width(raw(), part); }
		inline lv_coord_t getStyleShadowOfsX(uint32_t part) const { return lv_obj_get_style_shadow_ofs_x(raw(), part); }
		inline lv_coord_t getStyleShadowOfsY(uint32_t part) const { return lv_obj_get_style_shadow_ofs_y(raw(), part); }
		inline lv_coord_t getStyleShadowSpread(uint32_t part) const { return lv_obj_get_style_shadow_spread(raw(), part); }
		inline lv_color_t getStyleShadowColor(uint32_t part) const { return lv_obj_get_style_shadow_color(raw(), part); }
		inline lv_color_t getStyleShadowColorFiltered(uint32_t part) const { return lv_obj_get_style_shadow_color_filtered(raw(), part); }
		inline lv_opa_t getStyleShadowOpa(uint32_t part) const { return lv_obj_get_style_shadow_opa(raw(), part); }
		inline lv_opa_t getStyleImgOpa(uint32_t part) const { return lv_obj_get_style_img_opa(raw(), part); }
		inline lv_color_t getStyleImgRecolor(uint32_t part) const { return lv_obj_get_style_img_recolor(raw(), part); }
		inline lv_color_t getStyleImgRecolorFiltered(uint32_t part) const { return lv_obj_get_style_img_recolor_filtered(raw(), part); }
		inline lv_opa_t getStyleImgRecolorOpa(uint32_t part) const { return lv_obj_get_style_img_recolor_opa(raw(), part); }
		inline lv_coord_t getStyleLineWidth(uint32_t part) const { return lv_obj_get_style_line_width(raw(), part); }
		inline lv_coord_t getStyleLineDashWidth(uint32_t part) const { return lv_obj_get_style_line_dash_width(raw(), part); }
		inline lv_coord_t getStyleLineDashGap(uint32_t part) const { return lv_obj_get_style_line_dash_gap(raw(), part); }
		inline bool getStyleLineRounded(uint32_t part) const { return lv_obj_get_style_line_rounded(raw(), part); }
		inline lv_color_t getStyleLineColor(uint32_t part) const { return lv_obj_get_style_line_color(raw(), part); }
		inline lv_color_t getStyleLineColorFiltered(uint32_t part) const { return lv_obj_get_style_line_color_filtered(raw(), part); }
		inline lv_opa_t getStyleLineOpa(uint32_t part) const { return lv_obj_get_style_line_opa(raw(), part); }
		inline lv_coord_t getStyleArcWidth(uint32_t part) const { return lv_obj_get_style_arc_width(raw(), part); }
		inline bool getStyleArcRounded(uint32_t part) const { return lv_obj_get_style_arc_rounded(raw(), part); }
		inline lv_color_t getStyleArcColor(uint32_t part) const { return lv_obj_get_style_arc_color(raw(), part); }
		inline lv_color_t getStyleArcColorFiltered(uint32_t part) const { return lv_obj_get_style_arc_color_filtered(raw(), part); }
		inline lv_opa_t getStyleArcOpa(uint32_t part) const { return lv_obj_get_style_arc_opa(raw(), part); }
		inline const void *getStyleArcImgSrc(uint32_t part) const { return lv_obj_get_style_arc_img_src(raw(), part); }
		inline lv_color_t getStyleTextColor(uint32_t part) const { return lv_obj_get_style_text_color(raw(), part); }
		inline lv_color_t getStyleTextColorFiltered(uint32_t part) const { return lv_obj_get_style_text_color_filtered(raw(), part); }
		inline lv_opa_t getStyleTextOpa(uint32_t part) const { return lv_obj_get_style_text_opa(raw(), part); }
		inline const lv_font_t *getStyleTextFont(uint32_t part) const { return lv_obj_get_style_text_font(raw(), part); }
		inline lv_coord_t getStyleTextLetterSpace(uint32_t part) const { return lv_obj_get_style_text_letter_space(raw(), part); }
		inline lv_coord_t getStyleTextLineSpace(uint32_t part) const { return lv_obj_get_style_text_line_space(raw(), part); }
		inline lv_text_decor_t getStyleTextDecor(uint32_t part) const { return lv_obj_get_style_text_decor(raw(), part); }
		inline lv_text_align_t getStyleTextAlign(uint32_t part) const { return lv_obj_get_style_text_align(raw(), part); }
		inline lv_coord_t getStyleRadius(uint32_t part) const { return lv_obj_get_style_radius(raw(), part); }
		inline bool getStyleClipCorner(uint32_t part) const { return lv_obj_get_style_clip_corner(raw(), part); }
		inline lv_opa_t getStyleOpa(uint32_t part) const { return lv_obj_get_style_opa(raw(), part); }
		inline const lv_color_filter_dsc_t *getStyleColorFilterDsc(uint32_t part) const { return lv_obj_get_style_color_filter_dsc(raw(), part); }
		inline lv_opa_t getStyleColorFilterOpa(uint32_t part) const { return lv_obj_get_style_color_filter_opa(raw(), part); }
		inline uint32_t getStyleAnimTime(uint32_t part) const { return lv_obj_get_style_anim_time(raw(), part); }
		inline uint32_t getStyleAnimSpeed(uint32_t part) const { return lv_obj_get_style_anim_speed(raw(), part); }
		inline const lv_style_transition_dsc_t *getStyleTransition(uint32_t part) const { return lv_obj_get_style_transition(raw(), part); }
		inline lv_blend_mode_t getStyleBlendMode(uint32_t part) const { return lv_obj_get_style_blend_mode(raw(), part); }
		inline uint16_t getStyleLayout(uint32_t part) const { return lv_obj_get_style_layout(raw(), part); }
		inline lv_base_dir_t getStyleBaseDir(uint32_t part) const { return lv_obj_get_style_base_dir(raw(), part); }
		inline TSelf &setStyleWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleMinWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_min_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleMaxWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_max_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleHeight(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_height(raw(), value, selector), _self(); }
		inline TSelf &setStyleMinHeight(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_min_height(raw(), value, selector), _self(); }
		inline TSelf &setStyleMaxHeight(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_max_height(raw(), value, selector), _self(); }
		inline TSelf &setStyleX(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_x(raw(), value, selector), _self(); }
		inline TSelf &setStyleY(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_y(raw(), value, selector), _self(); }
		inline TSelf &setStyleAlign(lv_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_align(raw(), value, selector), _self(); }
		inline TSelf &setStyleTransformWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_transform_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleTransformHeight(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_transform_height(raw(), value, selector), _self(); }
		inline TSelf &setStyleTranslateX(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_translate_x(raw(), value, selector), _self(); }
		inline TSelf &setStyleTranslateY(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_translate_y(raw(), value, selector), _self(); }
		inline TSelf &setStyleTransformZoom(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_transform_zoom(raw(), value, selector), _self(); }
		inline TSelf &setStyleTransformAngle(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_transform_angle(raw(), value, selector), _self(); }
		inline TSelf &setStylePadTop(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_top(raw(), value, selector), _self(); }
		inline TSelf &setStylePadBottom(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_bottom(raw(), value, selector), _self(); }
		inline TSelf &setStylePadLeft(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_left(raw(), value, selector), _self(); }
		inline TSelf &setStylePadRight(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_right(raw(), value, selector), _self(); }
		inline TSelf &setStylePadRow(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_row(raw(), value, selector), _self(); }
		inline TSelf &setStylePadColumn(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_column(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgGradColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_grad_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgGradColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_grad_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgGradDir(lv_grad_dir_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_grad_dir(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgMainStop(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_main_stop(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgGradStop(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_grad_stop(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgGrad(const lv_grad_dsc_t *value, lv_style_selector_t selector) { return lv_obj_set_style_bg_grad(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgDitherMode(lv_dither_mode_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_dither_mode(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgSrc(const void *value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_src(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgRecolor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_recolor(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgRecolorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_recolor_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgRecolorOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_recolor_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleBgImgTiled(bool value, lv_style_selector_t selector) { return lv_obj_set_style_bg_img_tiled(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_border_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_border_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_border_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_border_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderSide(lv_border_side_t value, lv_style_selector_t selector) { return lv_obj_set_style_border_side(raw(), value, selector), _self(); }
		inline TSelf &setStyleBorderPost(bool value, lv_style_selector_t selector) { return lv_obj_set_style_border_post(raw(), value, selector), _self(); }
		inline TSelf &setStyleOutlineWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_outline_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleOutlineColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_outline_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleOutlineColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_outline_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleOutlineOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_outline_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleOutlinePad(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_outline_pad(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowOfsX(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_ofs_x(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowOfsY(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_ofs_y(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowSpread(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_spread(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleShadowOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_shadow_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleImgOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_img_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleImgRecolor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_img_recolor(raw(), value, selector), _self(); }
		inline TSelf &setStyleImgRecolorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_img_recolor_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleImgRecolorOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_img_recolor_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineDashWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_dash_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineDashGap(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_dash_gap(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineRounded(bool value, lv_style_selector_t selector) { return lv_obj_set_style_line_rounded(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleLineOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_line_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcWidth(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_arc_width(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcRounded(bool value, lv_style_selector_t selector) { return lv_obj_set_style_arc_rounded(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_arc_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_arc_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_arc_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleArcImgSrc(const void *value, lv_style_selector_t selector) { return lv_obj_set_style_arc_img_src(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextColor(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_color(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextColorFiltered(lv_color_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_color_filtered(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextFont(const lv_font_t *value, lv_style_selector_t selector) { return lv_obj_set_style_text_font(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextLetterSpace(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_letter_space(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextLineSpace(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_line_space(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextDecor(lv_text_decor_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_decor(raw(), value, selector), _self(); }
		inline TSelf &setStyleTextAlign(lv_text_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_text_align(raw(), value, selector), _self(); }
		inline TSelf &setStyleRadius(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_radius(raw(), value, selector), _self(); }
		inline TSelf &setStyleClipCorner(bool value, lv_style_selector_t selector) { return lv_obj_set_style_clip_corner(raw(), value, selector), _self(); }
		inline TSelf &setStyleOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleColorFilterDsc(const lv_color_filter_dsc_t *value, lv_style_selector_t selector) { return lv_obj_set_style_color_filter_dsc(raw(), value, selector), _self(); }
		inline TSelf &setStyleColorFilterOpa(lv_opa_t value, lv_style_selector_t selector) { return lv_obj_set_style_color_filter_opa(raw(), value, selector), _self(); }
		inline TSelf &setStyleAnimTime(uint32_t value, lv_style_selector_t selector) { return lv_obj_set_style_anim_time(raw(), value, selector), _self(); }
		inline TSelf &setStyleAnimSpeed(uint32_t value, lv_style_selector_t selector) { return lv_obj_set_style_anim_speed(raw(), value, selector), _self(); }
		inline TSelf &setStyleTransition(const lv_style_transition_dsc_t *value, lv_style_selector_t selector) { return lv_obj_set_style_transition(raw(), value, selector), _self(); }
		inline TSelf &setStyleBlendMode(lv_blend_mode_t value, lv_style_selector_t selector) { return lv_obj_set_style_blend_mode(raw(), value, selector), _self(); }
		inline TSelf &setStyleLayout(uint16_t value, lv_style_selector_t selector) { return lv_obj_set_style_layout(raw(), value, selector), _self(); }
		inline TSelf &setStyleBaseDir(lv_base_dir_t value, lv_style_selector_t selector) { return lv_obj_set_style_base_dir(raw(), value, selector), _self(); }
		inline TSelf &setStylePadAll(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_all(raw(), value, selector), _self(); }
		inline TSelf &setStylePadHor(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_hor(raw(), value, selector), _self(); }
		inline TSelf &setStylePadVer(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_ver(raw(), value, selector), _self(); }
		inline TSelf &setStylePadGap(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_pad_gap(raw(), value, selector), _self(); }
		inline TSelf &setStyleSize(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_size(raw(), value, selector), _self(); }
		inline lv_text_align_t calculateStyleTextAlign(lv_part_t part, const char *txt) const { return lv_obj_calculate_style_text_align(raw(), part, txt); }
		inline TSelf &initDrawRectDsc(uint32_t part, lv_draw_rect_dsc_t *draw_dsc) { return lv_obj_init_draw_rect_dsc(raw(), part, draw_dsc), _self(); }
		inline TSelf &initDrawLabelDsc(uint32_t part, lv_draw_label_dsc_t *draw_dsc) { return lv_obj_init_draw_label_dsc(raw(), part, draw_dsc), _self(); }
		inline TSelf &initDrawImgDsc(uint32_t part, lv_draw_img_dsc_t *draw_dsc) { return lv_obj_init_draw_img_dsc(raw(), part, draw_dsc), _self(); }
		inline TSelf &initDrawLineDsc(uint32_t part, lv_draw_line_dsc_t *draw_dsc) { return lv_obj_init_draw_line_dsc(raw(), part, draw_dsc), _self(); }
		inline TSelf &initDrawArcDsc(uint32_t part, lv_draw_arc_dsc_t *draw_dsc) { return lv_obj_init_draw_arc_dsc(raw(), part, draw_dsc), _self(); }
		inline lv_coord_t calculateExtDrawSize(uint32_t part) { return lv_obj_calculate_ext_draw_size(raw(), part); }
		inline TSelf &drawDscInit(lv_draw_ctx_t *draw_ctx) { return lv_obj_draw_dsc_init(raw(), draw_ctx), _self(); }
		inline bool drawPartCheckType(const struct _lv_obj_class_t *class_p, uint32_t type) { return lv_obj_draw_part_check_type(raw(), class_p, type); }
		inline TSelf &refreshExtDrawSize() { return lv_obj_refresh_ext_draw_size(raw()), _self(); }
		inline LvObjPtr classCreateObj(struct _lv_obj_t *parent) const { return (LvObjPtr)lv_obj_class_create_obj(raw(), parent); }
		inline TSelf &classInitObj() { return lv_obj_class_init_obj(raw()), _self(); }
		inline bool isEditable() { return lv_obj_is_editable(raw()); }
		inline bool isGroupDef() { return lv_obj_is_group_def(raw()); }
		inline lv_res_t eventBase(lv_event_t *e) const { return lv_obj_event_base(raw(), e); }
		inline struct _lv_event_dsc_t *addEventCb(lv_event_cb_t event_cb, lv_event_code_t filter, void *user_data) { return lv_obj_add_event_cb(raw(), event_cb, filter, user_data); }
		inline bool removeEventCb(lv_event_cb_t event_cb) { return lv_obj_remove_event_cb(raw(), event_cb); }
		inline bool removeEventCbWithUserData(lv_event_cb_t event_cb, const void *event_user_data) { return lv_obj_remove_event_cb_with_user_data(raw(), event_cb, event_user_data); }
		inline bool removeEventDsc(struct _lv_event_dsc_t *event_dsc) { return lv_obj_remove_event_dsc(raw(), event_dsc); }
		inline void *getEventUserData(lv_event_cb_t event_cb) { return lv_obj_get_event_user_data(raw(), event_cb); }
		inline TSelf &addFlag(lv_obj_flag_t f) { return lv_obj_add_flag(raw(), f), _self(); }
		inline TSelf &clearFlag(lv_obj_flag_t f) { return lv_obj_clear_flag(raw(), f), _self(); }
		inline TSelf &addState(lv_state_t state) { return lv_obj_add_state(raw(), state), _self(); }
		inline TSelf &clearState(lv_state_t state) { return lv_obj_clear_state(raw(), state), _self(); }
		inline TSelf &setUserData(void *user_data) { return lv_obj_set_user_data(raw(), user_data), _self(); }
		inline bool hasFlag(lv_obj_flag_t f) const { return lv_obj_has_flag(raw(), f); }
		inline bool hasFlagAny(lv_obj_flag_t f) const { return lv_obj_has_flag_any(raw(), f); }
		inline lv_state_t getState() const { return lv_obj_get_state(raw()); }
		inline bool hasState(lv_state_t state) const { return lv_obj_has_state(raw(), state); }
		inline LvGroup *getGroup() const { return (LvGroup *)lv_obj_get_group(raw()); }
		inline void *getUserData() { return lv_obj_get_user_data(raw()); }
		inline TSelf &allocateSpecAttr() { return lv_obj_allocate_spec_attr(raw()), _self(); }
		inline bool checkType(const lv_obj_class_t *class_p) const { return lv_obj_check_type(raw(), class_p); }
		inline bool hasClass(const lv_obj_class_t *class_p) const { return lv_obj_has_class(raw(), class_p); }
		inline const lv_obj_class_t *getClass() const { return lv_obj_get_class(raw()); }
		inline bool isValid() const { return lv_obj_is_valid(raw()); }
		inline lv_coord_t dpx(lv_coord_t n) const { return lv_obj_dpx(raw(), n); }
		inline TSelf &moveForeground() { return lv_obj_move_foreground(raw()), _self(); }
		inline TSelf &moveBackground() { return lv_obj_move_background(raw()), _self(); }
		inline uint32_t getChildId() const { return lv_obj_get_child_id(raw()); }
		inline TSelf &setFlexFlow(lv_flex_flow_t flow) { return lv_obj_set_flex_flow(raw(), flow), _self(); }
		inline TSelf &setFlexAlign(lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place) { return lv_obj_set_flex_align(raw(), main_place, cross_place, track_cross_place), _self(); }
		inline TSelf &setFlexGrow(uint8_t grow) { return lv_obj_set_flex_grow(raw(), grow), _self(); }
		inline TSelf &setStyleFlexFlow(lv_flex_flow_t value, lv_style_selector_t selector) { return lv_obj_set_style_flex_flow(raw(), value, selector), _self(); }
		inline TSelf &setStyleFlexMainPlace(lv_flex_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_flex_main_place(raw(), value, selector), _self(); }
		inline TSelf &setStyleFlexCrossPlace(lv_flex_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_flex_cross_place(raw(), value, selector), _self(); }
		inline TSelf &setStyleFlexTrackPlace(lv_flex_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_flex_track_place(raw(), value, selector), _self(); }
		inline TSelf &setStyleFlexGrow(uint8_t value, lv_style_selector_t selector) { return lv_obj_set_style_flex_grow(raw(), value, selector), _self(); }
		inline lv_flex_flow_t getStyleFlexFlow(uint32_t part) const { return lv_obj_get_style_flex_flow(raw(), part); }
		inline lv_flex_align_t getStyleFlexMainPlace(uint32_t part) const { return lv_obj_get_style_flex_main_place(raw(), part); }
		inline lv_flex_align_t getStyleFlexCrossPlace(uint32_t part) const { return lv_obj_get_style_flex_cross_place(raw(), part); }
		inline lv_flex_align_t getStyleFlexTrackPlace(uint32_t part) const { return lv_obj_get_style_flex_track_place(raw(), part); }
		inline uint8_t getStyleFlexGrow(uint32_t part) const { return lv_obj_get_style_flex_grow(raw(), part); }
		inline TSelf &setTile(lv_obj_t *tile_obj, lv_anim_enable_t anim_en) { return lv_obj_set_tile(raw(), tile_obj, anim_en), _self(); }
		inline TSelf &setTileId(uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) { return lv_obj_set_tile_id(raw(), col_id, row_id, anim_en), _self(); }
		inline TSelf &setGridDscArray(const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) { return lv_obj_set_grid_dsc_array(raw(), col_dsc, row_dsc), _self(); }
		inline TSelf &setGridAlign(lv_grid_align_t column_align, lv_grid_align_t row_align) { return lv_obj_set_grid_align(raw(), column_align, row_align), _self(); }
		inline TSelf &setGridCell(lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span) { return lv_obj_set_grid_cell(raw(), column_align, col_pos, col_span, row_align, row_pos, row_span), _self(); }
		inline TSelf &setStyleGridRowDscArray(const lv_coord_t value[], lv_style_selector_t selector) { return lv_obj_set_style_grid_row_dsc_array(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridColumnDscArray(const lv_coord_t value[], lv_style_selector_t selector) { return lv_obj_set_style_grid_column_dsc_array(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridRowAlign(lv_grid_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_row_align(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridColumnAlign(lv_grid_align_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_column_align(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellColumnPos(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_column_pos(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellColumnSpan(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_column_span(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellRowPos(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_row_pos(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellRowSpan(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_row_span(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellXAlign(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_x_align(raw(), value, selector), _self(); }
		inline TSelf &setStyleGridCellYAlign(lv_coord_t value, lv_style_selector_t selector) { return lv_obj_set_style_grid_cell_y_align(raw(), value, selector), _self(); }
		inline const lv_coord_t *getStyleGridRowDscArray(uint32_t part) const { return lv_obj_get_style_grid_row_dsc_array(raw(), part); }
		inline const lv_coord_t *getStyleGridColumnDscArray(uint32_t part) const { return lv_obj_get_style_grid_column_dsc_array(raw(), part); }
		inline lv_grid_align_t getStyleGridRowAlign(uint32_t part) const { return lv_obj_get_style_grid_row_align(raw(), part); }
		inline lv_grid_align_t getStyleGridColumnAlign(uint32_t part) const { return lv_obj_get_style_grid_column_align(raw(), part); }
		inline lv_coord_t getStyleGridCellColumnPos(uint32_t part) const { return lv_obj_get_style_grid_cell_column_pos(raw(), part); }
		inline lv_coord_t getStyleGridCellColumnSpan(uint32_t part) const { return lv_obj_get_style_grid_cell_column_span(raw(), part); }
		inline lv_coord_t getStyleGridCellRowPos(uint32_t part) const { return lv_obj_get_style_grid_cell_row_pos(raw(), part); }
		inline lv_coord_t getStyleGridCellRowSpan(uint32_t part) const { return lv_obj_get_style_grid_cell_row_span(raw(), part); }
		inline lv_coord_t getStyleGridCellXAlign(uint32_t part) const { return lv_obj_get_style_grid_cell_x_align(raw(), part); }
		inline lv_coord_t getStyleGridCellYAlign(uint32_t part) const { return lv_obj_get_style_grid_cell_y_align(raw(), part); }
		//+gen

		enum class EEventHandler
		{
			WithDeleter,
			WithoutDeletor,
		};

		template <EEventHandler T>
		struct EventHandler
		{
			void *pt;
		};

		template <lv_event_code_t... CODE, typename T>
		requires LvEvent<>::_isRealEvent<CODE...> || LvEvent<>::_isRealEvent<LvEvent<>::_parseCode<T>>
		inline decltype(auto) addListener(T &&event_cb) noexcept
		{
			constexpr bool ETyped = LvEvent<>::_isRealEvent<CODE...>;
			constexpr auto EFilter = ETyped ? lv_event_code_t((CODE | ... | 0)) : lv_event_code_t((CODE | ... | LvEvent<>::_parseCode<T>));
			using TEvent = std::conditional_t<ETyped, LvEvent<LvEvent<>::_realCode<CODE...>>, LvEvent<LvEvent<>::_parseCode<T>>>;
			static_assert(std::invocable<T, TEvent &>);
			if constexpr (sizeof(T) <= sizeof(void *) && std::is_trivially_move_constructible_v<T>)
			{
				void *pt;
				new (&pt) T{std::move(event_cb)};
				lv_obj_add_event_cb(
					raw(), [](lv_event_t *event) { ((T &)event->user_data)((TEvent &)*event); },
					EFilter, pt);
				if constexpr (!std::is_trivially_destructible_v<T>)
					lv_obj_add_event_cb(
						raw(), [](lv_event_t *event) { ((T &)event->user_data).~T(); },
						LV_EVENT_DELETE, pt);
				return; // can't remove explicit
			}
			else
			{
				auto pt = new (lv_mem_alloc(sizeof(T))) T{std::forward<T>(event_cb)};
				lv_obj_add_event_cb(
					raw(), [](lv_event_t *event) { (*(T *)event->user_data)((TEvent &)*event); },
					EFilter, pt);
				lv_obj_add_event_cb(
					raw(), [](lv_event_t *event) {if constexpr(!std::is_trivially_destructible_v<T>) ((T *)event->user_data)->~T(); lv_mem_free(event->user_data); },
					LV_EVENT_DELETE, pt);
				return EventHandler<EEventHandler::WithDeleter>{pt};
			}
		}

		template <lv_event_code_t... CODE>
		inline decltype(auto) addListener(auto &event_cb) = delete;

		template <lv_event_code_t CODE>
		inline void addListener(void (*event_cb)(LvEvent<CODE> &)) noexcept
		{
			lv_obj_add_event_cb(raw(), (lv_event_cb_t)event_cb, CODE, nullptr); // pointer and reference not same on syntax but should ok on abi
		}

		template <EEventHandler T>
		inline bool removeListener(EventHandler<T> hdl) noexcept { return lv_obj_remove_event_cb_with_user_data(raw(), nullptr, hdl.pt); }
	};

	using LvObj = LvTObj<lv_obj_t &&>;
	using LvObjRef = LvTObj<lv_obj_t> &;

} /* namespace lvglpp */

#endif /* LVOBJ_H_ */
